package com.sduept.nwld.kpi.manager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sduept.core.dao.SuperDAO;
import com.sduept.nwld.kpi.datasource.KpiDataSource;
import com.sduept.nwld.kpi.model.KpiGroup;
import com.sduept.nwld.kpi.model.KpiLevel;
import com.sduept.nwld.kpi.model.KpiNormal;
import com.sduept.nwld.kpi.model.KpiWeight;

@Service
public class KpiManager {
	@Autowired
	private SuperDAO dao;
	
	
	public List<KpiNormal> findKpiByGroup(String kpiGroup){
		return dao.findByCondition("kpiGroup = ?",new Object[]{kpiGroup},null,null,KpiNormal.class);
	}
	
	/**
	 * @param pid 不可为空，为空即方法findRoots
	 * @return
	 */
	public List<KpiGroup> findGroupByPid(String pid){
		return dao.findByCondition("pid = ?",new Object[]{pid},null,null,KpiGroup.class);
	}
	public List<KpiDataSource> findDataSourceByKpi(String pid){
		String sql = "select t2.id from tr_kpi_kpiweight t "
				+ "left join t_kpi_kpidatasource t2 "
				+ "on t.cid = t2.id "
				+ "where t.ptype = 'kpinormal' and t.ctype = 'kpidatasource' and t.pid = '"+pid+"';";
		List<?> res = dao.nativeQuery(sql);
		List<KpiDataSource> dss = new ArrayList<KpiDataSource>();
		for(int i=0;i<res.size();i++){
			dss.add(dao.findById(res.get(i).toString(), KpiDataSource.class));
		}
		return dss;
	}
	public List<KpiGroup> findGroupRoots(){
		return dao.findByCondition(" pid is null",KpiGroup.class);
	}
	public List<KpiLevel> findLevelsAllOrderByValue(){
		return dao.findAll(KpiLevel.class, " order by value desc ");
	}
	public List<KpiWeight> findWeightsByKpi(String kpiid){
//		return dao.findByCondition(" pid = '"+kpiid+"' ", KpiWeight.class);
		return dao.findByCondition(KpiWeight.class, " pid = ?", kpiid);
	}
	/**
	 * 删除KpiNormal类中id为参数值的项
	 * @param id
	 * @param T
	 */
	public void deleteKpiById(String id){
		//先把本kpi的可靠度置0，更新所有他是子的kpi的值。
		dao.nativeUpdate(" update t_kpi_kpinormal t set t.reliabilityValue = 0 "
				+ " where t.id = '"+id+"';");
		updateSelfAndParentsKpiReliability(id);
		//然后删掉他和父kpi，子kpi，数据源的关联关系
		dao.delete(KpiWeight.class, " cid = ? or pid = ? ", id,id);
		//删掉本kpi
		dao.delete(id, KpiNormal.class);
	}
	public void deleteDatasourceById(String id){
		//先把本ds的可靠度置0，更新所有基于他的kpi的值。
		dao.nativeUpdate("update t_kpi_kpidatasource t set t.reliabilityParam = 0 "
				+ "where t.id = '"+id+"';");
		updateDsParentsKpiReliability(id);
		//然后删掉他和父kpi的关联关系
		dao.delete(KpiWeight.class, " cid = ? ", id);
		//删掉本ds
		dao.delete(id, KpiDataSource.class);
	}
	/**
	 * 更新此kpi的可靠度，以及所有与之相关的kpi的可靠度
	 * @param id
	 */
	public Map<String,Integer> updateSelfAndParentsKpiReliability(String kpiid){
		Map<String,Integer> idRealiabilityValueMap = new HashMap<>();
		//更新本kpi的可靠度，存数据库
		int value = countKpiReliability(kpiid);
		dao.nativeUpdate("update t_kpi_kpinormal t set t.reliabilityValue = "
				+ value + " where t.id = '"+kpiid+"';");
		idRealiabilityValueMap.put(kpiid, value);
		//找到本kpi的父们
		List<KpiWeight> ps = dao.findByCondition(KpiWeight.class, 
				" ptype = ? and ctype = ? and cid = ? ", "kpinormal","kpinormal",kpiid);
		//更新父们的父
		for(KpiWeight p : ps){
			updateSelfAndParentsKpiReliability(p.getPid());
		}
		
		return idRealiabilityValueMap;
	}
	/**
	 * 更新与此数据源相关的所有kpi的可靠度
	 * @param dsid
	 * @return
	 */
	public Map<String,Integer> updateDsParentsKpiReliability(String dsid){
		Map<String,Integer> idRealiabilityValueMap = new HashMap<>();
		//找到引用此ds的所有kpi的id
		List<KpiWeight> ps = dao.findByCondition(KpiWeight.class, 
				" ptype = ? and ctype = ? and cid = ? ", "kpinormal","kpidatasource",dsid);
		for(KpiWeight p : ps){
			idRealiabilityValueMap.putAll(updateSelfAndParentsKpiReliability(p.getPid()));
		}
		return idRealiabilityValueMap;
	}
	public void removeDataSourceFromKpi(String dsid,String kpiid){
		//重置此ds对于此kpi的权重为0
		dao.nativeUpdate("update tr_kpi_kpiweight t set t.value = 0 "
				+ "where t.ctype = 'kpidatasource' and t.ptype = 'kpinormal' "
				+ "and t.cid = '"+dsid+"' and t.pid = '"+kpiid+"';");
		//重新计算kpi及kpi有关的kpi的可靠度
		updateSelfAndParentsKpiReliability(kpiid);
		//删除权重关系
		dao.delete(KpiWeight.class, " pid = ? and cid = ? and ptype = ? and ctype = ? ",kpiid,dsid,"kpinormal","kpidatasource");
	}
	public void removeKpiFromKpi(String pid,String cid){
		//重置此kpi对于父kpi的权重为0
		dao.nativeUpdate(" update tr_kpi_kpiweight t set t.value = 0 "
				+ "where t.ctype = 'kpinormal' and t.ptype = 'kpinormal' "
				+ "and t.cid = '"+cid+"' and t.pid = '"+pid+"';");
		//重新计算kpi及kpi有关的kpi的可靠度
		updateSelfAndParentsKpiReliability(pid);
		//删除权重关系
		dao.delete(KpiWeight.class, "pid = ? and cid = ? and ptype = ? and ctype = ? ",pid,cid,"kpinormal","kpinormal");
	}
	/**
	 * 删掉KpiGroup表中id为参数值的项
	 * @param id
	 */
	public void deleteGroupById(String id){
		for(KpiGroup g : findGroupByPid(id)){
			deleteGroupById(g.getId());
		}
		deleteKpiByGroup(id);
		dao.delete(id, KpiGroup.class);
	}
	/**
	 * 删掉KpiNormal表中kpiGroup为参数值的项
	 * @param groupId
	 */
	public <T> void deleteKpiByGroup(String kpiGroup){
		for(KpiNormal n : findKpiByGroup(kpiGroup)){
			deleteKpiById(n.getId());
		}
		dao.delete(kpiGroup, KpiGroup.class);
	}
	/**
	 * 验证Kpi的权重和，返回权重和
	 * @param kpiid
	 * @return
	 */
	public double validationKpiWeightByKpi(String kpiid){
//		List<KpiWeight> ds = dao.findByCondition("pid='"+kpiid+"'", KpiWeight.class);
		List<KpiWeight> ds = dao.findByCondition(KpiWeight.class, "pid = ?", kpiid);
		double w = 0;
		for(KpiWeight d : ds){
			w += d.getValue();
		}
		return w ;
	}
	/**
	 * 统计kpi的可靠度（统计所有数据源和子kpi的可靠度）
	 * @param kpiid
	 * @return
	 */
	public int countKpiReliability(String kpiid){
		//找到kpiweight里面的以他为父的weight，找到这些weight对应的可靠度，相加计算
		List<?> kpiValues = dao.nativeQuery("select t.value,t2.reliabilityValue from tr_kpi_kpiweight t "
				+ "left join t_kpi_kpinormal t2 on t.cid = t2.id " 
				+ "where t.ctype = 'kpinormal' and t.ptype = 'kpinormal' and t.pid = '"+kpiid+"';");
		List<?> dsValues = dao.nativeQuery("select t.value,t2.reliabilityParam from tr_kpi_kpiweight t "
				+ "left join t_kpi_kpidatasource t2 on t.cid = t2.id " 
				+ "where t.ctype = 'kpidatasource' and t.ptype = 'kpinormal' and t.pid = '"+kpiid+"';"	);
		double count = 0d;
		for(int i=0;i<kpiValues.size();i++){
			Object[] v = (Object[]) kpiValues.get(i);
			count += Double.parseDouble((v[0]).toString())*Double.parseDouble(v[1].toString());
		}
		for(int i=0;i<dsValues.size();i++){
			Object[] v = (Object[]) dsValues.get(i);
			count += Double.parseDouble((v[0]).toString())*Double.parseDouble(v[1].toString());
		}
		return (int) count ;
	}
	
	/**
	 * 根据等级找到所有指标
	 */
	public List<KpiNormal> findKpiByLevel(String kpiLevel){
//		return dao.findByCondition(" kpiLevel = '"+kpiLevel+"'",KpiNormal.class);
		return dao.findByCondition(KpiNormal.class, " kpiLevel = ?", kpiLevel);
	}
	/**
	 * 找到group下某level的所有kpi
	 */
	public List<KpiNormal> findKpiByGroupLevel(String groupId, String kpiLevelId){
		//根据groupId找到normal。根据level筛选normal
		List<KpiNormal> ns = findKpiByGroup(groupId);
		List<KpiNormal> result = new ArrayList<>();
		for(KpiNormal n : ns){
			if(n.getKpiLevel().equals(kpiLevelId)){
				result.add(n);
			}
		}
		return result;
	}
	/**
	 * 验证是否引用冲突（即此kpi的父是否已包含此childid）
	 * @param kpiid
	 * @param childid
	 * @return
	 */
	public boolean findImportKpiRepeatWithParent(String kpiid, String childid) {
		List<KpiWeight> ws = dao.findByCondition(KpiWeight.class, 
				" ctype = ? and ptype = ? and pid = ? ", "kpinormal","kpinormal",childid);
		for(KpiWeight w : ws){
			String cid = w.getCid();
			if(cid.equals(kpiid)){
				return true;
			}
			if(findImportKpiRepeatWithParent(kpiid,cid)){
				return true;
			}
		}
		return false;
	}
	/**
	 * 验证是否引用冲突（即此kpi的子是否已包含此childid）
	 * @param kpiid
	 * @param childid
	 * @return
	 */
	public boolean findImportKpiRepeatWithChild(String kpiid, String childid) {
		List<KpiWeight> ws = dao.findByCondition(KpiWeight.class, 
				" ctype = ? and ptype = ? and cid = ? and pid=?", "kpinormal","kpinormal",childid,kpiid);
		if(ws.size()>0){
			return true;
		}else{
			return false;
		}
	}
}
